package com.zh.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zh.blog.common.redis.RedisService;
import com.zh.blog.dao.CommentDao;
import com.zh.blog.dao.TalkDao;
import com.zh.blog.dto.CommentCountDto;
import com.zh.blog.dto.TalkBackDto;
import com.zh.blog.dto.TalkDto;
import com.zh.blog.exception.BizException;
import com.zh.blog.model.Talk;
import com.zh.blog.security.component.UserUtils;
import com.zh.blog.service.TalkService;
import com.zh.blog.util.BeanCopyUtils;
import com.zh.blog.util.CommonUtils;
import com.zh.blog.util.HTMLUtils;
import com.zh.blog.util.PageUtils;
import com.zh.blog.vo.ConditionVO;
import com.zh.blog.vo.PageResult;
import com.zh.blog.vo.TalkVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.zh.blog.constant.RedisPrefixConst.TALK_LIKE_COUNT;
import static com.zh.blog.constant.RedisPrefixConst.TALK_USER_LIKE;
import static com.zh.blog.enums.ArticleStatusEnum.PUBLIC;

/**
 * 说说服务实现
 * @author ZhengHao
 * Created At 2022/8/13.
 **/
@Service
public class TalkServiceImpl extends ServiceImpl<TalkDao, Talk> implements TalkService {
    @Autowired
    private TalkDao talkDao;
    @Autowired
    private CommentDao commentDao;
    @Autowired
    private RedisService redisService;
    @Override
    public TalkBackDto getBackTalkById(Integer talkId) {
        TalkBackDto talkBackDto = talkDao.getBackTalkById(talkId);
        // 转换图片格式
        if (Objects.nonNull(talkBackDto.getImages())) {
            talkBackDto.setImgList(CommonUtils.castList(JSON.parseObject(talkBackDto.getImages(), List.class),String.class));
        }
        return talkBackDto;
    }

    @Override
    public void saveOrUpdateTalk(TalkVO talkVO) {
        Talk talk = BeanCopyUtils.copyObject(talkVO, Talk.class);
        talk.setUserId(UserUtils.getLoginUser().getUserInfoId());
        this.saveOrUpdate(talk);
    }

    @Override
    public PageResult<TalkBackDto> listBackTalks(ConditionVO conditionVO) {
        // 查询说说总数
        Long count = talkDao.selectCount(new LambdaQueryWrapper<Talk>()
                .eq(Objects.nonNull(conditionVO.getStatus()), Talk::getStatus, conditionVO.getStatus()));
        if (count == 0) {
            return new PageResult<>();
        }
        // 分页查询说说
        List<TalkBackDto> talkBackDtoList = talkDao.listBackTalks(PageUtils.getLimitCurrent(), PageUtils.getSize(), conditionVO);
        talkBackDtoList.forEach(item -> {
            // 转换图片格式
            if (Objects.nonNull(item.getImages())) {
                item.setImgList(CommonUtils.castList(JSON.parseObject(item.getImages(), List.class),String.class));
            }
        });
        return new PageResult<>(talkBackDtoList, count);
    }

    @Override
    public void deleteTalks(List<Integer> talkIdList) {
        talkDao.deleteBatchIds(talkIdList);
    }

    @Override
    public List<String> listHomeTalks() {
        return talkDao.selectList(new LambdaQueryWrapper<Talk>()
                .eq(Talk::getStatus, PUBLIC.getStatus())
                .orderByDesc(Talk::getIsTop)
                .orderByDesc(Talk::getId).last("limit 10"))
           .stream()
                .map(item -> item.getContent().length() > 200 ? HTMLUtils.deleteHTMLTag(item.getContent().substring(0,200)) : HTMLUtils.deleteHTMLTag(item.getContent()))
                .collect(Collectors.toList());
    }

    @Override
    public PageResult<TalkDto> listTalks() {
        // 查询说说总量
        Long count = talkDao.selectCount(new LambdaQueryWrapper<Talk>()
                .eq(Talk::getStatus, PUBLIC.getStatus()));
        if (count == 0) {
            return new PageResult<>();
        }
        // 分页查询说说
        List<TalkDto> talkDtoList = talkDao.listTalks(PageUtils.getLimitCurrent(), PageUtils.getSize());
        // 查询说说评论量
        List<Integer> talkIdList = talkDtoList.stream()
                .map(TalkDto::getId)
                .collect(Collectors.toList());
        Map<Integer, Integer> commentCountMap =  commentDao.listCommentCountByTopicIds(talkIdList)
                .stream()
                .collect(Collectors.toMap(CommentCountDto::getId, CommentCountDto::getCommentCount));
        // 查询说说点赞量
        Map<String, Object> likeCountMap = redisService.hGetAll(TALK_LIKE_COUNT);
        talkDtoList.forEach(item -> {
            item.setLikeCount((Integer) likeCountMap.get(item.getId().toString()));
            item.setCommentCount(commentCountMap.get(item.getId()));
            // 转换图片格式
            if (Objects.nonNull(item.getImages())) {
                item.setImgList(CommonUtils.castList(JSON.parseObject(item.getImages(),List.class),String.class));
            }
        });
        return new PageResult<>(talkDtoList, count);
    }

    @Override
    public void saveTalkLike(Integer talkId) {
        // 判断是否点赞
        String talkLikeKey = TALK_USER_LIKE + UserUtils.getLoginUser().getUserInfoId();
        if (redisService.sIsMember(talkLikeKey, talkId)) {
            // 点过赞则删除说说id
            redisService.sRemove(talkLikeKey, talkId);
            // 说说点赞量-1
            redisService.hDecr(TALK_USER_LIKE, talkId.toString(),1L);
        } else {
            // 未点赞则增加说说ID
            redisService.sAdd(talkLikeKey, talkId);
            // 说说点赞量+1
            redisService.hIncr(TALK_USER_LIKE, talkId.toString(), 1L);
        }
    }

    @Override
    public TalkDto getTalkById(Integer talkId) {
        // 查询说说信息
        TalkDto talkDto = talkDao.getTalkById(talkId);
        if (Objects.isNull(talkDto)) {
            throw new BizException("说说不存在");
        }
        // 查询说说点赞量
        talkDto.setLikeCount((Integer) redisService.hGet(TALK_USER_LIKE, talkId.toString()));
        // 转换图片格式
        if (Objects.nonNull(talkDto.getImages())) {
            talkDto.setImgList(CommonUtils.castList(JSON.parseObject(talkDto.getImages(),List.class),String.class));
        }
        return talkDto;
    }
}